package leetcode每日一题.leetcode20212;

import java.util.Arrays;
import java.util.HashSet;

/**
 * 1. 问题描述
 *    爱丽丝和鲍勃有不同大小的糖果棒：A[i]是爱丽丝拥有的第i根糖果棒的大小，B[j]是鲍勃拥有的第j根糖果棒的大小。
 *    因为他们是朋友，所以他们想交换一根糖果棒，这样交换后，他们都有相同的糖果总量。
 *   （一个人拥有的糖果总量是他们拥有的糖果棒大小的总和。）
 *    返回一个整数数组 ans，其中 ans[0] 是爱丽丝必须交换的糖果棒的大小，ans[1] 是 Bob 必须交换的糖果棒的大小。
 *    如果有多个答案，你可以返回其中任何一个。保证答案存在。
 *
 * 2. 算法分析
 *       只需要交换一次
 *       交换的糖果一定是存在的
 *       首先总的糖果大小的总和是不变的
 *       交换之后每个人的糖果总和就是两个人的总和的一半
 *
 *
 *
 * 3. 代码实现
 */
@SuppressWarnings("all")
public class Q01_公平的糖果棒交换 {
    public static void main(String[] args) {

    }

    // 暴力法 时间复杂度为O(N^2)  空间复杂度为O(1)
    public int[] fairCandySwap1(int[] A, int[] B) {
        int[] res = new int[2];
        int sumA = 0;
        int sumB = 0;
        for(int i = 0; i < A.length; i++) {
            sumA += A[i];
        }
        for(int i = 0; i < B.length; i++) {
            sumB += B[i];
        }
        for(int i = 0; i < A.length; i++) {
            // 当前A的第i个去交换B中的所有
            for(int j = 0; j < B.length; j++) {
                if(sumA - A[i] + B[j] == sumB - B[j] + A[i]) {
                    res[0] = A[i];
                    res[1] = B[j];
                    return res;
                }
            }
        }
        return res;
    }

    // 双指针 + 排序  时间复杂度为O(nlogn)  空间复杂度为O(1)
    public int[] fairCandySwap2(int[] A, int[] B) {
        Arrays.sort(A);
        Arrays.sort(B);
        int[] res = new int[2];
        int sumA = 0;
        int sumB = 0;
        for(int i = 0; i < A.length; i++) {
            sumA += A[i];
        }
        for(int i = 0; i < B.length; i++) {
            sumB += B[i];
        }
        int i = 0;
        int j = 0;
        while(i < A.length || j < B.length) {
            int tempA = sumA - A[i] + B[j];
            int tempB = sumB - B[j] + A[i];
            if(tempA == tempB) {
                res[0] = A[i];
                res[1] = B[j];
                break;
            }
            if(tempA < tempB) {
                j++;
            } else {
                i++;
            }
        }
        return res;
    }

    // 哈希表
    // 查询 扫描其中一个，假设为B[i] 判断 B[i] + (sumA - sumB) / 2是否在A中
    public int[] fairCandySwap3(int[] A, int[] B) {
        int sumA = Arrays.stream(A).sum();
        int sumB = Arrays.stream(B).sum();
        int diff = sumA - sumB;
        HashSet<Integer> hash = new HashSet<>();
        // sumA - x + y = sumB - y + x
        // 2(x - y) = sumA - sumB
        // x = y + (sumA - sumB) / 2
        for(int y : B) { // 初始化hash
            hash.add(y + diff / 2);
        }
        int[] res = new int[2];
        for(int x : A) {
            if(hash.contains(x)) {
                res[0] = x;
                res[1] = x - diff / 2;
                break;
            }
        }
        return res;
    }
}
